package com.jd.oneday.month3;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * @author liulonghui19
 * 后缀表达式/逆波兰表达式的计算器求值
 */

public class Day19_Test {
    public static void main(String[] args) {
        //定义逆波兰表达式   (3+4)*5-6    =>    3 4 + 5 * 6 -
        //为了方便，逆波兰表达式的数字和符号用空格隔开
        String suffixExpression = "3 4 + 5 * 6 -";
        //1.先将"3 4 + 5 * 6 -"  放到ArrayList中
        //2.将ArrayList，传递给一个方法，遍历ArrayList 配合栈完成计算
        Day19_Test day19_test = new Day19_Test();
        List<String> list = day19_test.getListString(suffixExpression);
        System.out.println("suffixExpression = " + list);

        int res = day19_test.calculate(list);
        System.out.println(res);
    }

    /**
     * 将一个逆波兰表达式，依次将数据和运算符放入ArrayList中
     *
     * @param suffixExpression 需要分割后存入List中的字符串
     * @return
     */
    public List<String> getListString(String suffixExpression) {
        //将suffixExpression进行分割     按照空格分割
        String[] split = suffixExpression.split(" ");
        List<String> list = new ArrayList<>();
        //增强for循环，取出List中的元素
        for (String ele : split) {
            list.add(ele);
        }
        return list;
    }

    /**
     * 完成对逆波兰表达式的计算
     * 1.从左至右扫描，将3和4压入栈中
     * 2.遇到+运算符，因此弹出4和3（4为栈顶元素，3为次顶元素），计算得出3+4=7，再将7入栈
     * 3.将5入栈
     * 4.接下来是*运算符，因此弹出5和7，计算7*5=35，将35入栈
     * 5.将6入栈
     * 6.最后是-运算符，计算35-6=29，即29就是最终的结果
     *
     * @param list 需要运算的字符串
     * @return
     */
    public int calculate(List<String> list) {
        //创建一个栈，只需一个栈即可
        Stack<String> stack = new Stack<>();
        //遍历  list
        for (String item : list) {
            //使用正则表达式来取出数    匹配的是多位数
            if (item.matches("\\d+")) {
                //入栈
                stack.push(item);
            } else {
                //pop出两个数并运算，在入栈
                int num2 = Integer.parseInt(stack.pop());
                int num1 = Integer.parseInt(stack.pop());
                //存放计算结果
                int res = 0;
                if (item.equals("+")) {
                    res = num1 + num2;
                } else if (item.equals("-")) {
                    //注意减数与被减数顺序    位置
                    res = num1 - num2;
                } else if (item.equals("*")) {
                    res = num1 * num2;
                } else if (item.equals("/")) {
                    //注意除数与被除数顺序    位置
                    res = num1 / num2;
                } else {
                    throw new RuntimeException("运算符有误");
                }
                //把res 入栈   res转为字符串类型
                stack.push(res + "");
            }
        }
        //最后留着stack中的数据就是最后运算结果
        return Integer.parseInt(stack.pop());
    }
}
